/**************************************
 *
 * Programme : joueurHexx.C
 *
 * Synopsis : 
 *
 * Ecrit par : 
 * 
/***************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>

#include "joueurHexx.h"
#include "fonctionsTCP.h"



void coupToString(TypCoupReq ca,char* rep){

	sprintf(rep,"%d,%d,%d,%d,%d\n",
		ca.caseDepPiece.axeLettre,
		ca.caseDepPiece.axeChiffre,
		ca.caseArrPiece.axeLettre,
		ca.caseArrPiece.axeChiffre,
		ca.propCoup);

}

void stringToCoup(char* rep,TypCoupReq* mc,int maCouleur,int cptCoups){

	char * token;

	mc->idRequest = COUP;
	mc->couleurPiece = (maCouleur == 0) ? ROUGE : BLEU ;
	printf("%d\n", mc->couleurPiece);

	mc->numeroDuCoup = cptCoups;

	token = strsep(&rep, ",");
	mc->caseDepPiece.axeLettre = atoi(token);	
	printf("%s\n", token);

	token = strsep(&rep, ",");
	mc->caseDepPiece.axeChiffre = atoi(token);
	printf("%s\n", token);
	
	token = strsep(&rep, ",");
	mc->caseArrPiece.axeLettre = atoi(token);
	printf("%s\n", token);

	token = strsep(&rep, ",");
	mc->caseArrPiece.axeChiffre = atoi(token);
	printf("%s\n", token);

	token = strsep(&rep, ",");
	mc->bloq = atoi(token);
	printf("%s\n", token);
	
	token = strsep(&rep, ",");
	mc->propCoup = atoi(token);
	printf("%s\n", token);

}





int main(int argc, char **argv) {


	int sock,					/* descripteur de la socket locale */
		port,					/* variables de lecture */
		err,					/* code d'erreur */
		sockIA,
		portIA,
		client;
	char* nomMachine;

	int finTournoi ;			/* determine si il reste des parties */
	int recommencePartie = 0;	/* determine la fin d'une partie */

	int monTour = 0; 					/* a qui le tour ? */
	int maCouleur = 1;				/* ma couleur ( 0 rouge, 1 bleu )*/

	TypIdentificationReq tiReq; 	/* ma requete d'identification */
	TypIdentificationRep repMyId;	/* la réponse à ma requete d'ID */
	
	TypPartieReq reqMyPartie;		/* ma requete de partie */
	TypPartieRep repOurPartie;		/* la réponse à ma requête de partie */
	
	/* verification des arguments */
	if (argc != 5) {
		printf("usage : joueurHexx nom_machine no_port nom_joueur no_port_ia\n");
		exit(1);
	}

	nomMachine = argv[1];
	port = atoi(argv[2]);
	portIA = atoi(argv[4]);

	/********************************/
	sock = socketClient(nomMachine,port);
	sockIA = socketServeur(portIA);
	/********************************/

	//	1a-	création de l'objet d'identification 
		tiReq.idRequest = IDENTIFICATION ;
		strcpy(tiReq.nom,argv[3]);

	//	1b-	envoi de la requête IDENTIFICATION à l'arbitre
		err = send(sock, &tiReq, sizeof(TypIdentificationReq), 0);

		if (err != sizeof(TypIdentificationReq)) {
			perror("client : erreur sur le send d'IDENTIFICATION\n");
			shutdown(sock, 2); close(sock);
			exit(3);
		}

	//	1c-	reception de la réponse IDENTIFICATION de l'arbitre
		err = recv(sock, &repMyId, sizeof(repMyId), 0);
		printf("MY ID : %d-%d\n",repMyId.err,repMyId.joueur);

	//	1d- attente de la connexion du client Java

		if((client = accept(sockIA,(struct sockaddr*)NULL, 0))<0){
			printf("accept failed\n");
			perror(NULL);
			exit(-1);
		}

	//	2a-	envoi de la requête PARTIE à l'arbitre
				
		reqMyPartie.idRequest = PARTIE;
		reqMyPartie.joueur = repMyId.joueur;

		err = send(sock, &reqMyPartie, sizeof(TypPartieReq), 0);

		if (err != sizeof(TypPartieReq)) {
			perror("client : erreur sur le send de PARTIE\n");
			shutdown(sock, 2); close(sock);
			exit(3);
		}

	//	2b- reception de la réponse de l'arbitre

		err = recv(sock, &repOurPartie, sizeof(TypPartieRep), 0);
		printf("ADV ID : %d-%d\n",repOurPartie.err,repOurPartie.adversaire);

		if(repOurPartie.finTournoi == FAUX){
			finTournoi = 0;

			if(repOurPartie.premier == VRAI){
				monTour = 1;
				maCouleur = 0;
			}
		}else{
			finTournoi = 1;
		}

		char joueur[2] ;
		sprintf(joueur, "%d\n", maCouleur);

		printf("Envoi de la couleur à l'IA : envoi ->IA de %s",joueur);

		err = send(client, joueur, strlen(joueur), 0);


		// tant que le tournoi n'est pas fini
		while(finTournoi != 1){

			int advAJoue = 0;
			int cptCoups = 0;
			TypCoupReq coupAdverse;

			while(recommencePartie != 1){
				
				cptCoups++;

				if(monTour == 1){
				// 	3a-	Si c'est à mon tour, j'interroge mon IA pour connaitre le coup
				
				// Si je joue le 1er coup, je change ma couleur, et j'en avertis l'IA
					if(advAJoue == 0){

						char* rep = "a\n";
						printf("1er coup : envoi ->IA de %s",rep);

						err = send(client, rep, strlen(rep), 0);
					}else{
						
					// 	5	informe l'IA du coup joué par l'adversaire 
					//		(forcément bon, sinon la boucle se serait interrompue )
						
						char rep[10];

						coupToString(coupAdverse,rep);

						printf("coup normal : envoi ->IA coup adverse %s",rep);

						err = send(client, rep, strlen(rep), 0);
					}

					char rep[12];
					err = recv(client, rep, sizeof(rep), 0);
					printf("reception de mon nouveau coup :%d - %s \n", sizeof(rep),rep);
				
				//	3b-	création du coup avec le résultat de l'IA	
					TypCoupReq myCoup;
					stringToCoup(rep,&myCoup,maCouleur,cptCoups);
					printf("conversion : %d - %d\n",myCoup.caseDepPiece.axeLettre,myCoup.caseDepPiece.axeChiffre);
				
				//	3c-	envoi de la requete du coup
					err = send(sock, &myCoup, sizeof(TypCoupReq), 0);

					if (err != sizeof(TypCoupReq)) {
						perror("client : erreur sur le send de COUP\n");
						shutdown(sock, 2); close(sock);
						exit(3);
					}

				//	3d- reception de la réponse
					TypCoupRep repMyCoup;
					err = recv(sock, &repMyCoup, sizeof(TypCoupRep), 0);
					printf("mon coup : %d-%d\n",repMyCoup.err,repMyCoup.validCoup);

					// si fin de partie, on recommence la partie
					if(repMyCoup.validCoup != VALID || (repMyCoup.validCoup == VALID && myCoup.propCoup >= 2) ){
						printf(" Fin de partie ! (1)\n");
						recommencePartie = 1;
						char* rep = "o\n";
						err = send(client, rep, strlen(rep), 0);
						break;
					}

				}else{
				//	4a-	Attends le coup de l'adversaire

				//	4b-	Recois le TypCoupRep de l'arbitre validant ou non le coup de l'adversaire
					TypCoupRep	validCoupAdverse;
					err = recv(sock, &validCoupAdverse, sizeof(TypCoupRep), 0);


					//	4c-	Recois le coup joué par l'adversaire

					err = recv(sock, &coupAdverse, sizeof(TypCoupReq), 0);

					/*debug*/
					char res[12];
					coupToString(coupAdverse,res);
					printf("coup adverse : %s\n",res);
					/* fin debug*/

					
					//	Si je reçois un coup perdant ou gagnant de l'adversaire 
					if(	validCoupAdverse.validCoup != VALID || (validCoupAdverse.validCoup == VALID && coupAdverse.propCoup >= 2)){
						printf(" Fin de partie ! (2)\n");
						recommencePartie = 1;
						char* rep = "o\n";
						err = send(client, rep, strlen(rep), 0);
						break;
					}

					// 5 sinon j'informe l'IA que l'adversaire a joué (voir au dessus)
					advAJoue = 1;

				}
				monTour = (monTour+1)%2;
				printf("mon tour : %d",monTour);
			}


			//	2a-	envoi de la requête PARTIE à l'arbitre
			printf("Demande d'une nouvelle partie \n");
			reqMyPartie.idRequest = PARTIE;
			reqMyPartie.joueur = reqMyPartie.joueur;

			err = send(sock, &reqMyPartie, sizeof(TypPartieReq), 0);

			if (err != sizeof(TypPartieReq)) {
				perror("client : erreur sur le send de PARTIE\n");
				shutdown(sock, 2); close(sock);
				exit(3);
			}

			recommencePartie = 0;
			
		//	2b- reception de la réponse de l'arbitre
			err = recv(sock, &repOurPartie, sizeof(TypPartieRep), 0);
			printf("%d-%d\n",repOurPartie.err,repOurPartie.adversaire);

			if(repOurPartie.finTournoi == FAUX){
				finTournoi = 0;
				if(repOurPartie.premier == VRAI){
					monTour = 1;
				}else{
					monTour = 0;
				}
			}else{
				finTournoi = 1;
			}
		}

		printf("FIN DU TOURNOI \n");
		char* rep = "n\n";
		err = send(client, rep, strlen(rep), 0);

		shutdown(sockIA,2);
		close(sockIA);

		shutdown(sock,2);
		close(sock);

		return 0;

}